/**
 * @file STL_Timestamp.cpp
 * @author Derek Liu (yjkhtddx@sina.com)
 * @brief 
 * @version 0.1
 * @date 2020-09-10
 * 
 * @copyright Copyright Sci-Tech Laboratories (c) 2020
 * 
 */

#include "STL_Timestamp.h"
#include "STL_Tools.h"
#include "STLOG.h"
#include <sys/time.h> //gettimeofday
// #include <time.h> // time(null)
#include <string>
#include <regex>

namespace STL
{
    void printfTimestamp(const char *file, int line, const char *function, const char *title)
    {
        printf("\033["
               "36;40;1m"
               "[DEBUG %s:%d %s] => "
               "%s: %s\n"
               "\033[0m",
               file, line, function, title, getTimestampString("%F %T:%s").c_str());
    }

    long getTimestamp(long offset /* = 0*/)
    {
        struct timeval now;
        gettimeofday(&now, NULL);
        time_t timep = now.tv_sec;
        return (timep + offset);
        // return (time(null) + offset);
    }

    long getTimestampFromTime(std::string time) //2021-9-27 19:57:05
    {
        // stlog_debug("%s", time.c_str());
        time_t timestamp = getTimestamp();
        struct tm *tm = localtime(&timestamp);

        std::smatch sm_date;
        std::regex regDate("(\\d{4})-(\\d{1,2})-(\\d{1,2})");
        if (std::regex_search(time, sm_date, regDate))
        {
            // stlog_debug("-----------------------------");
            // for (int i = 0; i < sm_date.size(); i++)
            // {
            //     stlog_debug("%s", sm_date[i].str());
            // }
            // stlog_debug("-----------------------------");
            int year = std::stoi(sm_date[1].str()) - 1900;
            if (year >= 0)
                tm->tm_year = year;
            int mon = std::stoi(sm_date[2].str()) - 1;
            if (mon >= 0 && mon <= 11)
                tm->tm_mon = mon;
            int day = std::stoi(sm_date[3].str());
            if (day >= 1 && day <= 31)
                tm->tm_mday = day;
        }

        std::smatch sm_time;
        std::regex regTime("(\\d{1,2}):(\\d{1,2}):(\\d{1,2})");
        if (std::regex_search(time, sm_time, regTime))
        {
            // stlog_debug("-----------------------------");
            // for (int i = 0; i < sm_time.size(); i++)
            // {
            //     stlog_debug("%s", sm_time[i].str());
            // }
            // stlog_debug("-----------------------------");
            int hour = std::stoi(sm_time[1].str());
            if (hour >= 0 && hour <= 23)
                tm->tm_hour = hour;
            int min = std::stoi(sm_time[2].str());
            if (min >= 0 && min <= 59)
                tm->tm_min = min;
            int sec = std::stoi(sm_time[3].str());
            if (sec >= 0 && sec <= 59)
                tm->tm_sec = sec;
        }

        return mktime(tm);
    }

    long long getMillTimestamp(long long offset /* = 0*/)
    {
        struct timeval now;
        gettimeofday(&now, NULL);
        time_t timep = now.tv_sec;
        return (timep + offset) * 1000 + now.tv_usec / 1000;
    }

    std::string getTimestampString()
    {
        std::string format = "%F %T";
        return getTimestampString(format);
    }
    std::string getTimestampString(std::string format)
    {
        long long millTimestamp = getMillTimestamp();
        return getTimestampString(format, millTimestamp);
    }
    std::string getTimestampString(std::string format, long timestmap)
    {
        long long millTimestamp = ((long long)timestmap) * 1000;
        return getTimestampString(format, millTimestamp);
    }
    std::string getTimestampString(std::string format, long long millTimestamp)
    {
        char buffer[80];
        sprintf(buffer, "%03d", (int)(millTimestamp % 1000));
        std::size_t pos = format.find("%s");
        while (pos != std::string::npos)
        {
            format.replace(pos, 2, std::string(buffer));
            pos = format.find("%s", pos);
        }
        time_t timestmap = millTimestamp / 1000;
        struct tm *tm = localtime(&timestmap);
        strftime(buffer, 80, format.c_str(), tm);
        return std::string(buffer);
    }

} // namespace STL
